/*
Henry Chan
CPE301 Embedded Systems
Design Assignment #4
Dr. Venki Muthukumar
24 March 2014

This C program is designed to generate three PWM signals, each connected
to a lead of an RGB LED to produce various colors. The PWM signals are
created using 8-bit timers to change the frequency and period length
of each signal.

*/
#define F_CPU 1000000L	//define cpu clock

#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/io.h>

uint8_t i = 0;	//magnitude of brightness
uint8_t j = 0;	//variable to alter frequency
uint8_t k = 0;	//variable to alter frequency

int main(void)
{
	DDRD |= _BV(PD5);	// set OC0B pin as output, required for output toggling
	DDRD |= _BV(PD6);	// set OC0A pin as output, required for output toggling
	DDRB |= _BV(PB3);	// set OC2A pin as output, required for output toggling
	DDRB |= _BV(PB1);	// set OC1A pin as output, required for output toggling
	DDRC = 0xff;

	PORTB = 0x00; // set output high -> turn all LEDs off
	PORTD = 0x00;
	PORTC = 0x00;
	
	sei();	//enable interrupts
	
	TIMSK0 = _BV(TOIE0); //allow timer0 overflow interrupt
	// enable 8 bit Fast PWM with clear OC0A/OC0B pins on Compare Match
	TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
	TCCR0B = _BV(CS00);	// no prescalar
	TCNT0 = 26; //start with min period (90%)
	
	TIMSK2 = _BV(TOIE2); //allow timer2 overflow interrupt
	// enable 8 bit Fast PWM with clear OC2A pin on Compare Match
	TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
	TCCR2B = _BV(CS20); // no prescale
	TCNT2 = 26; //start with min period (90%)
	
	TIMSK1 = _BV(TOIE1);	//enable Timer1 overflow interrupt
	TCCR1A = _BV(COM1A1) | _BV(WGM10);	//Set Timer1 mode to fast pwm 8-bit
	TCCR1B = _BV(WGM12) | _BV(CS10);	//no Prescalar
	TCNT1L = 26; //start with min period (90%)
	
	while(1)
	{
		int a=0;
		/*fade LED on*/
		for(a=0;a<(255-26-i);a++){
			OCR0A=26+a;
			OCR1A=26+a;
			OCR2A=26+a;
			_delay_ms(10); //delay 10 ms just to slow things down
		}
		/*fade LED off*/
		for(a=(255-26-i);a>0;a--){
			OCR0A=26+a;
			OCR1A=26+a;
			OCR2A=26+a;
			_delay_ms(10); //delay 10 ms just to slow things down
		}
	}
	return 0;
}

/*
The following interrupts will change the periods
of the signals in order for the respective color to
change shade
*/
ISR(TIMER0_OVF_vect){
	cli();
	i++;
	TCNT0 = 26+i;
	OCR0A = ((255-TCNT0)/2)+TCNT0;	//50% duty cycle
	if(TCNT0==230){
		i=0;
	}
	//_delay_ms(10); //delay 10 ms just to slow things down
	sei();
}
ISR(TIMER2_OVF_vect){
	cli();
	if(i>=203)	//when timer0 has run through all its colors
		j++;	//start the next color for timer2
	TCNT2 = 26+j;
	OCR2A = ((255-TCNT2)/2)+TCNT2;	//50% duty cycle
	if(TCNT2==230){
		j=0;
	}
	//_delay_ms(10); //delay 10 ms just to slow things down
	sei();
}
ISR(TIMER1_OVF_vect){
	cli();
	if(j>=203)	//when timer2 has run through all its colors
		k++;	//start the next color for timer1
	TCNT1L = 26+k;
	OCR1A = ((255-TCNT1)/2)+TCNT1;	//50% duty cycle
	if(TCNT1L==230){
		k=0;
	}
	//_delay_ms(10); //delay 10 ms just to slow things down
	sei();
	//PORTC ^= (1 << 0);		//Toggle PORTC.0
	//TCNT1 = 0x0BDC;			//Set Timer1 count value to 3036
}